from collections import OrderedDict
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from datetime import datetime
from django.http.response import JsonResponse
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.serializers import JSONWebTokenSerializer

jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER
from rest_framework import mixins
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.views import JSONWebTokenAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework import status
from rest_framework.pagination import PageNumberPagination
from rest_framework import viewsets
from django.db.models import Q
from utils.sms import Tencent_SMS
from utils import gen_random_str
from utils.permissions import IsOwnerOrReadOnly
from .serializers import SMSSerializer, UserRegisterSerializer, UserDetailSerializer, UserAddressSerializer
from .models import VerifyCode, UserAddress, UserInfo
from utils.weibo import Weibo
from shop.settings import client_id, client_secret
from apps.utils.custom_response import CustomPagination
from django.views import View
import json

User = get_user_model()


class QueryUser(View):
    def post(self, request):
        phone = json.loads(request.body.decode()).get('mobile')
        is_exist = UserInfo.objects.filter(Q(username=phone) | Q(mobile=phone))
        data = {
            'code': 200,
            'message': 'success',
            'data': True if is_exist else False
        }
        return JsonResponse(data)


class WeiboLogin(APIView):
    """
    微博登录
    """

    def get(self, request):
        code = request.GET.get('code')
        weibo = Weibo(client_id, client_secret, code)
        print(weibo.get_access_token())


class UserPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'pageSize'
    page_query_param = 'page'

    def get_paginated_response(self, data):
        info = {
            'code': 200,
            'message': '操作成功',
            'data': OrderedDict([
                ('pageNum', 1),
                ('pageSize', 10),
                ('list', data),
                ('total', self.page.paginator.count),
                ('totalPage', self.page.number)
            ]),

        }
        return Response(info)


class CustomJSONWebTokenAPIView(JSONWebTokenAPIView):

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            user = serializer.object.get('user') or request.user
            token = serializer.object.get('token')
            response_data = jwt_response_payload_handler(token, user, request)
            response = Response(response_data)
            if api_settings.JWT_AUTH_COOKIE:
                expiration = (datetime.utcnow() +
                              api_settings.JWT_EXPIRATION_DELTA)
                response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                    token,
                                    expires=expiration,
                                    httponly=True)

            return response
            #   在utils处理
            #
            # current = UserInfo.objects.get(username=user)
            # current.last_login = datetime.now()
            # current.save()
            # response.data = {
            #     'code': 200,
            #     'message': "操作成功",
            #     'data': {
            #         'token': response.data,
            #         'tokenHead': "Bearer "
            #     }
            # }
            # return response
        else:
            msg = serializer.errors.values()
            print(msg)
            data = {
                'code': 1000,
                'message': '用户名或密码错误，请检查',
                # 'message': '\n'.join([x[0] for x in msg]),
                'data': {}
            }

            return Response(data, status=status.HTTP_200_OK)
            # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class CustomObtainJSONWebToken(CustomJSONWebTokenAPIView):
    """
    jwt 登录重写
    """
    serializer_class = JSONWebTokenSerializer


class CustomBackend(ModelBackend):
    """
    用户登录 多方式
    """

    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username) | Q(mobile=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None


class SMSViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet, mixins.RetrieveModelMixin):
    """
    用户注册第一步  手机号
    """
    serializer_class = SMSSerializer
    queryset = VerifyCode.objects.all()
    lookup_field = 'mobile'

    def retrieve(self, request, *args, **kwargs):
        mobile = kwargs.get('mobile')
        # instance = self.get_object()
        # serializer = self.get_serializer(instance)
        # serializer.is_valid(raise_exception=True)
        # mobile = serializer.validated_data['mobile']
        code = VerifyCode.objects.filter(mobile=mobile).last()
        print(code, 'hello')
        data = {
            'code': 200,
            'message': 'success',
            'data': str(code) if code else '0'
        }
        return Response(data, status.HTTP_200_OK)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        mobile = serializer.validated_data['mobile']
        code = gen_random_str()
        sms_response = Tencent_SMS(mobile, code).send_code()
        if sms_response['errmsg'] != 'OK':
            data = {
                'code': 1005,
                'message': sms_response['errmsg'],
                'data': ''
            }
            return Response(data, status=status.HTTP_200_OK)
        else:
            code_record = VerifyCode(mobile=mobile, code=code)
            code_record.save()
            data = {
                'code': 200,
                'message': 'success',
                'data': ''
            }
            return Response(data, status=status.HTTP_200_OK)


class UserRegisterViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin,
                          viewsets.GenericViewSet):
    """
    用户注册第二部  存到数据库
    查询用户信息
    """
    serializer_class = UserRegisterSerializer
    queryset = User.objects.all()
    # pagination_class = CustomPagination
    # 添加权限 SessionAuthentication
    authentication_classes = (JSONWebTokenAuthentication,)

    # 鉴权
    # permission_classes = (IsAuthenticated,)

    # 动态鉴权
    def get_permissions(self):
        if self.action == 'retrieve':
            return [IsAuthenticated()]
        elif self.action == 'create':
            return []

        return []

    def get_object(self):
        # 只返回单个用户
        return self.request.user

    # 动态序列化
    def get_serializer_class(self):
        if self.action == 'retrieve':
            return UserDetailSerializer
        elif self.action == 'create':
            return UserRegisterSerializer

        return UserDetailSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=status.HTTP_200_OK, headers=headers)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)


class UserAddressViewSet(viewsets.ModelViewSet):
    """
    地址
    """
    authentication_classes = (JSONWebTokenAuthentication,)
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    serializer_class = UserAddressSerializer
    pagination_class = CustomPagination

    def get_queryset(self):
        return UserAddress.objects.filter(user=self.request.user)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=200)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': ''
        }
        return Response(data, status=200)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)

        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=status.HTTP_200_OK, headers=headers)
        # return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)


# sentry测试
def trigger_error(request):
    division_by_zero = 1 / 0
